package com.ccteam.fluidmusic.ui.playlist

import android.support.v4.media.MediaMetadataCompat
import androidx.lifecycle.*
import com.ccteam.fluidmusic.fluidmusic.common.MusicServiceConnectionFlow
import com.ccteam.fluidmusic.fluidmusic.common.utils.MediaIDHelper
import com.ccteam.fluidmusic.fluidmusic.media.extensions.id
import com.ccteam.fluidmusic.utils.Event
import com.ccteam.fluidmusic.utils.cancelIfActive
import com.ccteam.fluidmusic.utils.setValueIfNew
import com.ccteam.fluidmusic.view.bean.ErrorMessage
import com.ccteam.fluidmusic.view.bean.LoadMessage
import com.ccteam.fluidmusic.view.bean.MoreInfoData
import com.ccteam.model.Resource
import com.ccteam.model.playlistsheet.PLAYLIST_SHEET_TYPE_PRIVATE
import com.ccteam.shared.core.UserCore
import com.ccteam.shared.domain.playlistsheet.AddHotPlaylistSheetCountDataUseCase
import com.ccteam.shared.domain.playlistsheet.PlaylistSheetDeleteDataUseCase
import com.ccteam.shared.domain.playlistsheet.PlaylistSheetDeleteMusicDataUseCase
import com.ccteam.shared.domain.playlistsheet.PlaylistSheetDetailDataUseCase
import com.ccteam.shared.result.playlistsheet.PlaylistSheetDetailHeaderItem
import com.ccteam.shared.result.playlistsheet.PlaylistSheetMusicItem
import com.ccteam.shared.utils.NO_PLAYING
import com.ccteam.shared.utils.PLAYING
import dagger.hilt.android.lifecycle.HiltViewModel
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.Job
import kotlinx.coroutines.flow.collectLatest
import kotlinx.coroutines.launch
import javax.inject.Inject

/**
 * @author Xiaoc
 * @since 2021/3/16
 *
 * 歌单详情页面ViewModel
 * 对歌单进行增改删，并且对歌单音乐进行控制和管理
 */
@HiltViewModel
class PlaylistSheetDetailViewModel @Inject constructor(
    private val userCore: UserCore,
    private val mediaIDHelper: MediaIDHelper,
    private val musicServiceConnectionFlow: MusicServiceConnectionFlow,
    private val playlistSheetDeleteMusicDataUseCase: PlaylistSheetDeleteMusicDataUseCase,
    private val playlistSheetDeleteDataUseCase: PlaylistSheetDeleteDataUseCase,
    private val playlistSheetDetailDataUseCase: PlaylistSheetDetailDataUseCase,
    private val addHotPlaylistSheetCountDataUseCase: AddHotPlaylistSheetCountDataUseCase,
    savedStateHandle: SavedStateHandle
): ViewModel() {

    private val playlistSheetResult = MutableLiveData<
            Resource<PlaylistSheetDetailDataUseCase.PlaylistSheetDetailUseCaseResult>>(Resource.Loading(null))

    /**
     * 歌单详情头部内容
     */
    val playlistSheetHeader: LiveData<List<PlaylistSheetDetailHeaderItem>> = playlistSheetResult.map {
        it.data?.playlistSheetHeader?.let { header ->
            listOf(header)
        } ?: emptyList()
    }

    /**
     * 歌单详情歌曲列表内容
     */
    private val _playlistSheetMusicList = MediatorLiveData<List<PlaylistSheetMusicItem>>()
    val playlistSheetMusicList: LiveData<List<PlaylistSheetMusicItem>> get() = _playlistSheetMusicList

    private val playlistSheetId = MutableLiveData<String>()

    var parentId: String? = null

    val loadMessage: LiveData<LoadMessage> = playlistSheetResult.map {
        when(it){
            is Resource.Success ->{
                if(it.data?.playlistSheetHeader == null || it.data!!.playlistSheetMusicList.isNullOrEmpty()){
                    LoadMessage.Empty
                } else {
                    LoadMessage.NotLoading
                }
            }
            is Resource.Loading ->{
                LoadMessage.Loading
            }
            is Resource.Error ->{
                LoadMessage.Error(ErrorMessage(it.message,it.errorCode))
            }
        }
    }

    private val _deletePlaylistLoadMessage = MutableLiveData<Event<LoadMessage>>()
    val deletePlaylistLoadMessage: LiveData<Event<LoadMessage>> get() = _deletePlaylistLoadMessage

    private val _deleteMusicLoadMessage = MutableLiveData<Event<LoadMessage>>()
    val deleteMusicLoadMessage: LiveData<Event<LoadMessage>> get() = _deleteMusicLoadMessage

    private val _shouldShowShareButton = MediatorLiveData<Boolean>()
    val shouldShowShareButton: LiveData<Boolean> get() = _shouldShowShareButton

    val isLogin = MutableLiveData<Boolean>()

    private var metadataChangedJob: Job? = null
    private var loginCheckJob: Job? = null

    init {
        _playlistSheetMusicList.addSource(playlistSheetId){
            parentId = mediaIDHelper.createMediaId(MediaIDHelper.ONLINE_MEDIA_PLAYLIST_SHEET,it)
            refreshPlaylistDetail()
        }

        playlistSheetId.setValueIfNew(savedStateHandle["playlistSheetId"])

        /**
         * 监听音乐信息变化，如果变化更新歌单歌曲列表状态
         */
        metadataChangedJob = viewModelScope.launch(Dispatchers.Default) {
            musicServiceConnectionFlow.nowPlaying.collectLatest {
                _playlistSheetMusicList.postValue(updateMusicList(it))
            }
        }

        _shouldShowShareButton.addSource(isLogin){
            _shouldShowShareButton.value = it && !playlistSheetHeader.value.isNullOrEmpty()
        }
        _shouldShowShareButton.addSource(playlistSheetHeader){
            _shouldShowShareButton.value = !it.isNullOrEmpty() && isLogin.value == true
        }
        loginCheckJob = viewModelScope.launch {
            userCore.isLogin.collectLatest {
                isLogin.value = it
            }
        }
    }

    /**
     * 刷新歌单信息
     */
    fun refreshPlaylistDetail(){

        playlistSheetId.value?.let { playlistSheetId ->
            parentId?.let { parentId ->
                viewModelScope.launch {
                    playlistSheetDetailDataUseCase(Pair(parentId,playlistSheetId)).collectLatest {
                        playlistSheetResult.value = it

                        _playlistSheetMusicList.value = it.data?.playlistSheetMusicList ?: emptyList()

                        // 如果请求成功，则执行加入到热门歌单操作
                        if(it is Resource.Success){
                            if(it.data?.playlistSheetHeader?.type != PLAYLIST_SHEET_TYPE_PRIVATE){
                                it.data?.playlistSheetHeader?.id?.let { playlistId ->
                                    addHotPlaylistSheetCountDataUseCase(playlistId)
                                }
                            }
                        }
                    }
                }
            }
        }
    }

    /**
     * 删除歌单操作
     */
    fun deletePlaylistSheet(){
        if(!playlistSheetHeader.value.isNullOrEmpty()){
            viewModelScope.launch {
                val result = playlistSheetDeleteDataUseCase(playlistSheetHeader.value!![0].id)

                if(result is Resource.Success){
                    _deletePlaylistLoadMessage.value = Event(LoadMessage.Success)
                } else {
                    _deletePlaylistLoadMessage.value = Event(LoadMessage.Error(ErrorMessage(result.message,result.errorCode)))
                }
            }
        }

    }

    /**
     * 删除歌单中的音乐
     */
    fun deletePlaylistSheetMusic(moreInfoData: MoreInfoData){
        if(playlistSheetId.value != null && !playlistSheetHeader.value.isNullOrEmpty()){
            viewModelScope.launch {
                val result = playlistSheetDeleteMusicDataUseCase(Pair(playlistSheetId.value!!,moreInfoData.id!!))

                if(result is Resource.Success){
                    _deleteMusicLoadMessage.value = Event(LoadMessage.Success)
                } else {
                    _deleteMusicLoadMessage.value = Event(LoadMessage.Error(ErrorMessage(result.message,result.errorCode)))
                }
            }
        }
    }

    /**
     * 更新歌单音乐状态
     * 当播放歌曲变动后，需要进行更新
     */
    private fun updateMusicList(metadata: MediaMetadataCompat): List<PlaylistSheetMusicItem>{
        return _playlistSheetMusicList.value?.map {
            it.copy(playbackRes = if (it.mediaId == metadata.id) PLAYING else NO_PLAYING)
        } ?: emptyList()
    }

    override fun onCleared() {
        super.onCleared()

        metadataChangedJob.cancelIfActive()
    }
}